#include <string.h>

#include "st7735s.h"
#include "img.h"


//SCL--->主机的时钟信号
void SPI_WriteData(uint8_t Data)
{
    HAL_SPI_Transmit(&hspi2, &Data, 1, 1000);
}

void Lcd_WriteCmd(uint8_t Cmd)
{
    LCD_CS_LOW;
	LCD_DC_LOW;
	SPI_WriteData(Cmd);
    LCD_CS_HIGH;
}

void Lcd_WriteData(uint8_t Data)
{
    LCD_CS_LOW;
	LCD_DC_HIGH;
	SPI_WriteData(Data);
    LCD_CS_HIGH;
}

void Lcd_WriteMem(uint16_t *pixel, uint32_t size)
{
	HAL_SPI_Transmit(&hspi2, (uint8_t *)pixel, size*2, 1000);
}

/*在SPI_WriteData（）基础上封装成16bit处理*/
void Lcd_WriteData_16bit(uint16_t Data)
{
	LCD_CS_LOW;
    LCD_DC_HIGH; 
    SPI_WriteData(Data>>8);//
    SPI_WriteData(Data);
    LCD_CS_HIGH;
}


void Lcd_Init(void)
{	
	
	Lcd_WriteCmd(0x01);
	HAL_Delay(1000);

	//LCD显示关
	Lcd_WriteCmd(0x28);
	//LCD Init For 1.44Inch LCD Panel with ST7735.
	Lcd_WriteCmd(0x11);//Sleep exit 
	HAL_Delay(120);
		
	/*1.若你为了快速完成工作需求，只需要理解功能即可
	直接复制粘贴下面代码，会移植就0K.
	  2.若你有大把的空闲时间（学生），建议还是学会翻阅Datasheet
	弄清原理，打好基础，深入了解液晶屏的底层驱动
	  3.精通一种型号屏的底层驱动，万变不离其中，其他屏也信手拈来*/	
	   
	//ST7735R Frame Rate
	Lcd_WriteCmd(0xB1); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 

	Lcd_WriteCmd(0xB2); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 

	Lcd_WriteCmd(0xB3); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 
	
	//显示反转控制
	Lcd_WriteCmd(0xB4);
	Lcd_WriteData(0x07); 
	
	//ST7735R 电源设置
	Lcd_WriteCmd(0xC0); 
	Lcd_WriteData(0xA2); 
	Lcd_WriteData(0x02); 
	Lcd_WriteData(0x84); 
	Lcd_WriteCmd(0xC1); 
	Lcd_WriteData(0xC5); 

	Lcd_WriteCmd(0xC2); 
	Lcd_WriteData(0x0A); 
	Lcd_WriteData(0x00); 

	Lcd_WriteCmd(0xC3); 
	Lcd_WriteData(0x8A); 
	Lcd_WriteData(0x2A); 
	Lcd_WriteCmd(0xC4); 
	Lcd_WriteData(0x8A); 
	Lcd_WriteData(0xEE); 
	
	Lcd_WriteCmd(0xC5); //VCOM 
	Lcd_WriteData(0x0E); 
	
	// 反色控制
	Lcd_WriteCmd(0x21);
	
	//内存数据访问控制
	Lcd_WriteCmd(0x36); //MX, MY, RGB mode 
	Lcd_WriteData(XY_Mirror|Vertical_Refresh_ToTOP|BGR|Horizontal_Refresh_ToLeft); 
	
	//ST7735R Gamma（“+”极性）校正特性设置
	Lcd_WriteCmd(0xe0); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x1a); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x18); 
	Lcd_WriteData(0x2f); 
	Lcd_WriteData(0x28); 
	Lcd_WriteData(0x20); 
	Lcd_WriteData(0x22); 
	Lcd_WriteData(0x1f); 
	Lcd_WriteData(0x1b); 
	Lcd_WriteData(0x23); 
	Lcd_WriteData(0x37); 
	Lcd_WriteData(0x00); 	
	Lcd_WriteData(0x07); 
	Lcd_WriteData(0x02); 
	Lcd_WriteData(0x10); 

	//ST7735R 伽玛（“-”极性）校正特性设置
	Lcd_WriteCmd(0xe1); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x1b); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x17); 
	Lcd_WriteData(0x33); 
	Lcd_WriteData(0x2c); 
	Lcd_WriteData(0x29); 
	Lcd_WriteData(0x2e); 
	Lcd_WriteData(0x30); 
	Lcd_WriteData(0x30); 
	Lcd_WriteData(0x39); 
	Lcd_WriteData(0x3f); 
	Lcd_WriteData(0x00); 
	Lcd_WriteData(0x07); 
	Lcd_WriteData(0x03); 
	Lcd_WriteData(0x10);  
	
	//设置像素传输格式
	Lcd_WriteCmd(0x3A); //65k mode 
	Lcd_WriteData(0x05); 
	
	Lcd_WriteCmd(0x29);//Display on	 


}


void Set_Position(unsigned char XB, unsigned char YB, unsigned char XE, unsigned char YE)
{
	Lcd_WriteCmd(0x2a);
	Lcd_WriteData(0x00);
	Lcd_WriteData(DeviationY + XB);
	Lcd_WriteData(0x00);
	Lcd_WriteData(DeviationY - 1 + XE);
	
	Lcd_WriteCmd(0x2b);
	Lcd_WriteData(0x00);
	Lcd_WriteData(DeviationX + YB);
	Lcd_WriteData(0x00);
	Lcd_WriteData(DeviationX - 1 + YE);
}

void LCE_Fill_Memory(unsigned char XB, unsigned char YB, unsigned char XE, unsigned char YE, unsigned int memory)
{
	int i,j;
	unsigned char Xsize = XE - XB;
	unsigned char Ysize = YE - YB;
	
	Set_Position(XB, YB, XE, YE);

	Lcd_WriteCmd(0x2C);
	for(i=0;i<Xsize;i++)
	{
		for(j=0;j<Ysize;j++)
		{
			Lcd_WriteData_16bit(memory);
		}
	}
}


void LCD_Fill(int color)
{          
	int i,j;
	Set_Position(0, 0, Width, Length);
	
	Lcd_WriteCmd(0x2C);
    for(i=0;i<Length;i++)
    {                                                                
        for(j=0;j<Width;j++)
        {
            Lcd_WriteData_16bit(color);
        }
    }              

}



void LCD_Fill_picture(unsigned short *pic)
{          
	int i,j;
	Set_Position(0, 0, Width, Length);
	
	Lcd_WriteCmd(0x2C);
	
    for(i=0;i<Length;i++)
    {                                                                
        for(j=0;j<Width;j++)
        {
            Lcd_WriteData_16bit(*pic);
			pic++;
        }
    }      
}


// 从RGB565颜色中提取RGB分量  
void RGB565ToRGB(uint16_t color, uint8_t *r, uint8_t *g, uint8_t *b) {  
    *r = ((color >> 11) & 0x1F) << 3; // 5位转换为8位  
    *g = ((color >> 5) & 0x3F) << 2;  // 6位转换为8位  
    *b = (color & 0x1F) << 3;         // 5位转换为8位  
}  
  
// 将RGB分量转换为RGB565颜色  
uint16_t RGBToRGB565(uint8_t r, uint8_t g, uint8_t b) {  
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);  
}  
  
// 使用灰度值插值两个RGB565颜色  
uint16_t interpolateRGB565Colors(uint16_t color1, uint16_t color2, uint8_t grayscale) {  
    uint8_t r1, g1, b1, r2, g2, b2;  
    RGB565ToRGB(color1, &r1, &g1, &b1);  
    RGB565ToRGB(color2, &r2, &g2, &b2);  
  
    // 使用灰度值进行线性插值  
    uint8_t r = (uint8_t)((float)(r2 - r1) * (grayscale / 255.0f) + r1);  
    uint8_t g = (uint8_t)((float)(g2 - g1) * (grayscale / 255.0f) + g1);  
    uint8_t b = (uint8_t)((float)(b2 - b1) * (grayscale / 255.0f) + b1);  
  
    // 将插值后的RGB值转换回RGB565格式  
    return RGBToRGB565(r, g, b);  
}  

void WriteMemry_8H9W(lcd_t lcd, const unsigned char *pic)
{
	for(int j=0; j < 80; j++)
	{
		Lcd_WriteData_16bit(interpolateRGB565Colors(lcd.color, lcd.bkColor, pic[j]));
	}
}

void WriteMemry_9H11W(lcd_t lcd, const unsigned char *pic)
{
	for(int j=0; j < 99; j++)
	{
		Lcd_WriteData_16bit(interpolateRGB565Colors(lcd.color, lcd.bkColor, pic[j]));
	}
}

void Lcd_Draw_Font_8H10W(lcd_t lcd, char * string)
{
	uint8_t x,y;
	uint8_t size = strlen(string);
	
	x = lcd.X;
	y = lcd.Y;
	
	for(int i = 0; i < size; i++)
	{
		Set_Position(x, y, x+8, y+10);
		Lcd_WriteCmd(0x2C);

		switch (*string)
		{
			case 'T':
				WriteMemry_8H9W(lcd, Font8H10W_T);
				break;
			
			case 'X':
				WriteMemry_8H9W(lcd, Font8H10W_X);
				break;
			
			case 'D':
				WriteMemry_8H9W(lcd, Font8H10W_D);
				break;

			case 'N':
				WriteMemry_8H9W(lcd, Font8H10W_N);
				break;

			case 'V':
				WriteMemry_8H9W(lcd, Font8H10W_V);
				break;

			case 'C':
				WriteMemry_8H9W(lcd, Font8H10W_C);
				break;

			case 'G':
				WriteMemry_8H9W(lcd, Font8H10W_G);
				break;

			case 'R':
				WriteMemry_8H9W(lcd, Font8H10W_R);
				break;
			
			default:
				break;
		}

		string++;

		x = x + 9;
	}
}

void Lcd_Draw_Font_14H17W(lcd_t lcd, char * string)
{
	uint8_t x,y;
	uint8_t size = strlen(string);
	
	x = lcd.X;
	y = lcd.Y;
	
	for(int i = 0; i < size; i++)
	{
		Set_Position(x, y, x+9, y+11);
		Lcd_WriteCmd(0x2C);

		switch (*string)
		{
			case 'U':
				WriteMemry_9H11W(lcd, Font_9H11W_U);
				break;
			
			case 'A':
				WriteMemry_9H11W(lcd, Font_9H11W_A);
				break;
			
			case 'R':
				WriteMemry_9H11W(lcd, Font_9H11W_R);
				break;

			case 'T':
				WriteMemry_9H11W(lcd, Font_9H11W_T);
				break;
			
			case '1':
				WriteMemry_9H11W(lcd, Font_9H11W_1);
				break;
			
			case '2':
				WriteMemry_9H11W(lcd, Font_9H11W_2);
				break;
			
			case '3':
				WriteMemry_9H11W(lcd, Font_9H11W_3);
				break;
			
			case '4':
				WriteMemry_9H11W(lcd, Font_9H11W_4);
				break;
			
			default:
				break;
		}

		string++;

		x = x + 10;
	}
}
